﻿﻿﻿﻿﻿using jiuyuan.数据.基础数据类;
using jiuyuan.数据.怪物类;
using jiuyuan.数据.玩家类;
using jiuyuan.服务;
using System.Collections.Concurrent;

namespace jiuyuan.管理器;

// 副本状态枚举
public enum 副本状态
{
    未开始,
    进行中,
    已完成,
    已失败,
    已放弃
}

// 副本实例类
public class 副本实例
{
    public Guid Id { get; set; } = Guid.CreateVersion7();
    public 副本配置 配置 { get; set; } = null!;
    public List<玩家> 玩家队伍 { get; set; } = [];
    public 战斗上下文? 当前战斗 { get; set; }
    public 副本状态 状态 { get; set; } = 副本状态.未开始;
    public int 当前波次 { get; set; } = 0;
    public int 总波次 { get; set; }
    public DateTime 开始时间 { get; set; }
    public DateTime? 结束时间 { get; set; }
    public List<游戏元素> 已获得奖励 { get; set; } = []; // 修改为游戏元素类型

    /// <summary>
    /// 检查副本是否完成
    /// </summary>
    public bool 是否完成 => 状态 == 副本状态.已完成 || 状态 == 副本状态.已失败 || 状态 == 副本状态.已放弃;

    /// <summary>
    /// 检查是否所有波次都已完成
    /// </summary>
    public bool 所有波次完成 => 当前波次 >= 总波次;

    /// <summary>
    /// 获取当前波次的怪物配置
    /// </summary>
    public List<怪物生成配置> 获取当前波次怪物()
    {
        if (当前波次 < 配置.怪物生成配置列表.Count)
        {
            return [.. 配置.怪物生成配置列表.Skip(当前波次).Take(1)];
        }
        return [];
    }
}

// 副本管理器
public class 副本管理器
{
    private readonly 战斗管理器 _战斗管理器;
    private readonly 事件总线 _事件总线;
    private readonly ILogger<副本管理器> _日志器;
    private readonly ConcurrentDictionary<Guid, 副本实例> _活跃副本 = new();

    public 副本管理器(战斗管理器 战斗管理器, 事件总线 事件总线, ILogger<副本管理器> 日志器)
    {
        _战斗管理器 = 战斗管理器;
        _事件总线 = 事件总线;
        _日志器 = 日志器;

        // 注册事件处理
        注册事件处理();
    }

    /// <summary>
    /// 创建副本实例
    /// </summary>
    public 副本实例 创建副本(副本配置 配置, List<玩家> 玩家队伍)
    {
        // 验证玩家等级
        foreach (var 玩家 in 玩家队伍)
        {
            if (玩家.等级 < 配置.等级要求)
            {
                throw new InvalidOperationException($"玩家 {玩家.名称} 等级不足，需要等级 {配置.等级要求}");
            }
        }

        var 副本 = new 副本实例
        {
            配置 = 配置,
            玩家队伍 = 玩家队伍,
            状态 = 副本状态.未开始,
            当前波次 = 0,
            总波次 = 配置.怪物生成配置列表.Count,
            开始时间 = DateTime.Now
        };

        _活跃副本[副本.Id] = 副本;

        _日志器.LogInformation("创建副本实例: {副本名称}, ID: {副本ID}, 玩家数量: {玩家数量}",
            配置.名称, 副本.Id, 玩家队伍.Count);

        return 副本;
    }

    /// <summary>
    /// 开始副本
    /// </summary>
    public async Task<bool> 开始副本(副本实例 副本)
    {
        if (副本.状态 != 副本状态.未开始)
        {
            _日志器.LogWarning("副本 {副本名称} 状态为 {当前状态}，无法开始", 副本.配置.名称, 副本.状态);
            return false;
        }

        副本.状态 = 副本状态.进行中;
        _日志器.LogInformation("开始副本: {副本名称}, ID: {副本ID}", 副本.配置.名称, 副本.Id);

        // 发布副本开始事件
        await _事件总线.发布事件(new 副本开始事件 { 副本实例 = 副本 });

        // 开始第一波战斗
        return await 开始下一波战斗(副本);
    }

    /// <summary>
    /// 开始下一波战斗
    /// </summary>
    public async Task<bool> 开始下一波战斗(副本实例 副本)
    {
        if (副本.所有波次完成)
        {
            _日志器.LogInformation("副本 {副本名称} 所有波次已完成", 副本.配置.名称);
            return await 完成副本(副本, true);
        }

        var 当前波次怪物配置 = 副本.获取当前波次怪物();
        if (当前波次怪物配置.Count == 0)
        {
            _日志器.LogWarning("副本 {副本名称} 第 {当前波次} 波没有怪物配置", 副本.配置.名称, 副本.当前波次);
            return await 完成副本(副本, true);
        }

        // 创建当前波次的战斗配置
        var 战斗配置 = new 副本配置
        {
            名称 = $"{副本.配置.名称} - 第{副本.当前波次 + 1}波",
            等级要求 = 副本.配置.等级要求,
            推荐人数 = 副本.配置.推荐人数,
            怪物生成配置列表 = 当前波次怪物配置
        };

        _日志器.LogInformation("开始副本 {副本名称} 第 {当前波次} 波战斗", 副本.配置.名称, 副本.当前波次 + 1);

        // 开始战斗
        var 战斗结果 = await _战斗管理器.开始战斗(战斗配置, 副本.玩家队伍);

        // 处理战斗结果
        if (战斗结果.玩家胜利)
        {
            副本.当前波次++;
            _日志器.LogInformation("副本 {副本名称} 第 {当前波次} 波战斗胜利", 副本.配置.名称, 副本.当前波次);

            // 检查是否还有下一波
            if (副本.所有波次完成)
            {
                // 发放通关奖励
                await 发放通关奖励(副本);
                return await 完成副本(副本, true);
            }
            else
            {
                // 等待玩家准备下一波（这里可以添加等待逻辑）
                _日志器.LogInformation("等待玩家准备下一波战斗...");
                return true;
            }
        }
        else
        {
            _日志器.LogInformation("副本 {副本名称} 第 {当前波次} 波战斗失败", 副本.配置.名称, 副本.当前波次 + 1);
            return await 完成副本(副本, false);
        }
    }

    /// <summary>
    /// 玩家准备下一波战斗
    /// </summary>
    public async Task<bool> 玩家准备下一波(副本实例 副本, 玩家 玩家)
    {
        if (副本.状态 != 副本状态.进行中)
        {
            _日志器.LogWarning("副本 {副本ID} 不在进行中状态", 副本.Id);
            return false;
        }

        if (副本.所有波次完成)
        {
            _日志器.LogWarning("副本 {副本ID} 所有波次已完成", 副本.Id);
            return false;
        }

        _日志器.LogDebug("玩家 {玩家名称} 准备下一波战斗", 玩家.名称);

        // 检查是否所有存活玩家都已准备
        var 存活玩家 = 副本.玩家队伍.Where(p => p.是否存活).ToList();
        var 已准备玩家 = 存活玩家; // 这里应该有一个准备状态，简化处理

        if (已准备玩家.Count == 存活玩家.Count)
        {
            _日志器.LogInformation("所有玩家已准备，开始下一波战斗");
            return await 开始下一波战斗(副本);
        }

        return true;
    }

    /// <summary>
    /// 放弃副本
    /// </summary>
    public async Task<bool> 放弃副本(副本实例 副本)
    {
        if (副本.状态 != 副本状态.进行中)
        {
            _日志器.LogWarning("副本 {副本ID} 不在进行中状态，无法放弃", 副本.Id);
            return false;
        }

        副本.状态 = 副本状态.已放弃;
        副本.结束时间 = DateTime.Now;

        _日志器.LogInformation("放弃副本: {副本名称}, ID: {副本ID}", 副本.配置.名称, 副本.Id);

        // 发布副本放弃事件
        await _事件总线.发布事件(new 副本放弃事件 { 副本实例 = 副本 });

        // 从活跃副本中移除
        _活跃副本.TryRemove(副本.Id, out _);

        return true;
    }

    /// <summary>
    /// 完成副本
    /// </summary>
    private async Task<bool> 完成副本(副本实例 副本, bool 胜利)
    {
        副本.状态 = 胜利 ? 副本状态.已完成 : 副本状态.已失败;
        副本.结束时间 = DateTime.Now;

        _日志器.LogInformation("完成副本: {副本名称}, 结果: {结果}", 副本.配置.名称, 胜利 ? "胜利" : "失败");

        // 发布副本完成事件
        await _事件总线.发布事件(new 副本完成事件
        {
            副本实例 = 副本,
            胜利 = 胜利
        });

        // 从活跃副本中移除
        _活跃副本.TryRemove(副本.Id, out _);

        return 胜利;
    }

    /// <summary>
    /// 发放通关奖励
    /// </summary>
    private async Task 发放通关奖励(副本实例 副本)
    {
        if (副本.配置.通关奖励 == null || 副本.配置.通关奖励.Count == 0)
        {
            _日志器.LogInformation("副本 {副本名称} 没有通关奖励", 副本.配置.名称);
            return;
        }

        var 随机数生成器 = new Random();
        foreach (var 玩家 in 副本.玩家队伍.Where(p => p.是否存活))
        {
            foreach (var 掉落 in 副本.配置.通关奖励)
            {
                if (随机数生成器.NextDouble() < 掉落.掉落概率)
                {
                    int 数量 = 随机数生成器.Next(掉落.最小数量, 掉落.最大数量 + 1);

                    if (掉落.物品详情 != null)
                    {
                        // 实际应该创建新的物品实例
                        玩家.仓库物品.Add(掉落.物品详情);
                        副本.已获得奖励.Add(掉落.物品详情); // 这里需要修复类型问题

                        _日志器.LogInformation("玩家 {玩家名称} 获得奖励: {物品名称} x {数量}",
                            玩家.名称, 掉落.物品详情.名称, 数量);

                        // 发布获得奖励事件
                        await _事件总线.发布事件(new 获得奖励事件
                        {
                            玩家 = 玩家,
                            物品 = 掉落.物品详情,
                            数量 = 数量,
                            来源 = $"副本通关: {副本.配置.名称}"
                        });
                    }
                }
            }
        }
    }

    /// <summary>
    /// 获取副本实例
    /// </summary>
    public 副本实例? 获取副本(Guid 副本Id)
    {
        return _活跃副本.TryGetValue(副本Id, out var 副本) ? 副本 : null;
    }

    /// <summary>
    /// 获取所有活跃副本
    /// </summary>
    public List<副本实例> 获取所有活跃副本()
    {
        return _活跃副本.Values.ToList();
    }

    /// <summary>
    /// 获取玩家所在的副本
    /// </summary>
    public 副本实例? 获取玩家所在副本(玩家 玩家)
    {
        return _活跃副本.Values.FirstOrDefault(副本 =>
            副本.玩家队伍.Any(p => p.Id == 玩家.Id));
    }

    /// <summary>
    /// 注册事件处理
    /// </summary>
    private void 注册事件处理()
    {
        // 处理战斗结束事件
        _事件总线.订阅事件<战斗结束事件>(async 事件 =>
        {
            // 查找对应的副本实例
            var 副本 = _活跃副本.Values.FirstOrDefault(f => f.当前战斗 == 事件.战斗上下文);
            if (副本 != null)
            {
                // 战斗结束后，副本管理器会处理下一波逻辑
                _日志器.LogDebug("副本 {副本名称} 战斗结束，结果: {结果}",
                    副本.配置.名称, 事件.玩家胜利 ? "胜利" : "失败");
            }
        });

        // 处理单位死亡事件（在副本中）
        _事件总线.订阅事件<单位死亡事件>(async 事件 =>
        {
            var 副本 = _活跃副本.Values.FirstOrDefault(f =>
                f.玩家队伍.Contains(事件.死亡单位) ||
                f.当前战斗?.怪物队伍.Contains((怪物)事件.死亡单位) == true);

            if (副本 != null)
            {
                _日志器.LogDebug("副本 {副本名称} 中单位死亡: {单位名称}",
                    副本.配置.名称, 事件.死亡单位.名称);
            }
        });
    }
}

// 副本相关事件
public class 副本开始事件 : 游戏事件
{
    public 副本实例 副本实例 { get; set; } = null!;
}

public class 副本完成事件 : 游戏事件
{
    public 副本实例 副本实例 { get; set; } = null!;
    public bool 胜利 { get; set; }
}

public class 副本放弃事件 : 游戏事件
{
    public 副本实例 副本实例 { get; set; } = null!;
}

public class 获得奖励事件 : 游戏事件
{
    public 玩家 玩家 { get; set; } = null!;
    public 游戏元素 物品 { get; set; } = null!;
    public int 数量 { get; set; }
    public string 来源 { get; set; } = string.Empty;
}